package com.packtpub.learningcypher.chapter4;

import java.util.concurrent.TimeUnit;
import org.neo4j.cypher.javacompat.ExecutionEngine;
import org.neo4j.graphdb.DynamicLabel;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.schema.IndexDefinition;
import org.neo4j.graphdb.schema.Schema;

/**
 * Examples with Schema: indexes and constraints
 * 
 * @author Onofrio Panzarino
 */
public class SchemaIndexes {

    private final ExecutionEngine engine;
    private final GraphDatabaseService graphDb;

    public SchemaIndexes(ExecutionEngine engine, GraphDatabaseService graphDb) {
        this.engine = engine;
        this.graphDb = graphDb;
    }

    public void addLabelIndexWithCypher() {
        engine.execute("CREATE INDEX ON :User(email)");
    }

    public void addLabelIndex() {
        IndexDefinition indexDefinition;
        try (Transaction tx = graphDb.beginTx()) {
            Schema schema = graphDb.schema();
            indexDefinition = schema.indexFor(DynamicLabel.label("User"))
                    .on("email")
                    .create();
            tx.success();
        }
        waitForIndexCreated(indexDefinition);
    }
    
    public void addConstraint() {
        engine.execute("CREATE CONSTRAINT ON(user:User) ASSERT user.userId IS UNIQUE");
        waitForAllIndexes();
    }

    private void waitForIndexCreated(IndexDefinition indexDefinition) {
        try (Transaction tx = graphDb.beginTx()) {
            Schema schema = graphDb.schema();
            schema.awaitIndexOnline(indexDefinition, 10, TimeUnit.SECONDS);
        }
    }
    
    private void waitForAllIndexes() {
        try (Transaction tx = graphDb.beginTx()) {
            Schema schema = graphDb.schema();
            schema.awaitIndexesOnline(1, TimeUnit.MINUTES);
        }
    }
}
